module AsyncTransmitter(
  iClk, 
  iTxStart, 
  iTxData, 
  oTx, 
  oTxBusy
);

input iClk, iTxStart;
input [7:0] iTxData;
output reg oTx;
output oTxBusy;

// -------------- Parameters -------------------------------------------------------------
parameter CLK_FREQUENCY = 50000000; // 50MHz
parameter BAUD = 115200;
// BAUD generator
parameter BAUDGENERATOR_ACC_WIDTH = 16;
parameter BAUDGENERATOR_INC = ((BAUD<<(BAUDGENERATOR_ACC_WIDTH-4))+(CLK_FREQUENCY>>5))/(CLK_FREQUENCY>>4);

//---------------- Internal registers and wires -------------------------------------------
reg [BAUDGENERATOR_ACC_WIDTH:0] baudGeneratorAcc = 0;
wire baudTick = baudGeneratorAcc[BAUDGENERATOR_ACC_WIDTH];
reg [3:0] state = 0;
reg muxbit = 0;

//---------------- assigns --------------------------------------
assign oTxBusy = (state != 0);

//---------------- always blocks --------------------------------------
always @(posedge iClk) begin 
  if(oTxBusy) begin
    baudGeneratorAcc <= baudGeneratorAcc[BAUDGENERATOR_ACC_WIDTH-1:0] + BAUDGENERATOR_INC;
  end
end

always @(posedge iClk) begin
  case(state)
    4'b0000: if(iTxStart) state <= 4'b0100;
    4'b0100: if(baudTick) state <= 4'b1000;  // start
    4'b1000: if(baudTick) state <= 4'b1001;  // bit 0
    4'b1001: if(baudTick) state <= 4'b1010;  // bit 1
    4'b1010: if(baudTick) state <= 4'b1011;  // bit 2
    4'b1011: if(baudTick) state <= 4'b1100;  // bit 3
    4'b1100: if(baudTick) state <= 4'b1101;  // bit 4
    4'b1101: if(baudTick) state <= 4'b1110;  // bit 5
    4'b1110: if(baudTick) state <= 4'b1111;  // bit 6
    4'b1111: if(baudTick) state <= 4'b0001;  // bit 7
    4'b0001: if(baudTick) state <= 4'b0010;  // stop1
    4'b0010: if(baudTick) state <= 4'b0000;  // stop2
    default: if(baudTick) state <= 4'b0000;
  endcase
end

// Output mux
always @(state[2:0] or iTxData) begin
  case(state[2:0])
    0: muxbit <= iTxData[0];
    1: muxbit <= iTxData[1];
    2: muxbit <= iTxData[2];
    3: muxbit <= iTxData[3];
    4: muxbit <= iTxData[4];
    5: muxbit <= iTxData[5];
    6: muxbit <= iTxData[6];
    7: muxbit <= iTxData[7];
  endcase
end

// Put together the start, data and stop bits
always @(posedge iClk) begin
  oTx <= (state<4) | (state[3] & muxbit);  // register the output to make it glitch free
end

endmodule
